<!--
 * @Author: swc
 * @Date: 2023-10-16 15:00:45
 * @LastEditors: zss
 * @LastEditTime: 2024-11-02 14:31:39
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <vxe-modal
    v-model="modalShow"
    :title="selectRow ? '编辑&保存' : '新增&保存'"
    width="800"
    min-width="600"
    min-height="300"
    :loading="submitLoading"
    resize
    destroy-on-close
    :before-hide-method="hideModal"
    :z-index="999999"
  >
    <template #default>
      <div class="modal">
        <div class="modal-body y-scroll">
          <div class="module" v-for="(val, key) in groupedItms" :key="key">
            <div class="module-title">{{ $srv.getI18nBySrv(key) }}:</div>
            <div class="module-content">
              <p
                v-for="(item, idx) in val"
                :key="idx"
                v-show="item.isShow"
                class="item"
              >
                <span class="item-k">
                  <i v-if="item.required" class="i-must-input-icon">*</i>
                  {{
                    item.alias
                      ? $srv.getI18nBySrv(item.alias)
                      : $srv.getI18nBySrv(item.field)
                  }}:
                </span>
                <!-- <span v-if="item.disabled" class="item-v">
                  {{
                    item.many2one &&
                    item.many2one.toField !== '' &&
                    item.many2one.toTable !== ''
                      ? getDS(item)
                      : item.value
                  }}
                </span> -->
                <Input
                  v-if="item.comp.name === 'Input'"
                  v-model="item.value"
                  :disabled="item.disabled"
                  :type="item.comp.type || 'text'"
                  class="item-v"
                  @on-enter="emitEvent(item, 'enter')"
                  @on-focus="emitEvent(item, 'focus')"
                  @on-blur="emitEvent(item, 'blur')"
                  @on-change="emitEvent(item, 'change')"
                  @mouseleave="emitEvent(item, 'mouseleave')"
                  @mouseenter="emitEvent(item, 'mouseenter')"
                />
                <o-m2o-selector
                  v-else-if="item.comp.name === 'idSelect'"
                  v-model="item.value"
                  :disabled="item.disabled"
                  :isFromTable="true"
                  :renderOpts="item.many2one.editRender"
                  :params="item.many2one.params"
                  :isFunLayout="false"
                  @on-dochange="m2oChange(item, $event)"
                  class="item-v"
                ></o-m2o-selector>
                <Select
                  v-else-if="item.comp.name === 'valueSelect'"
                  v-model="item.value"
                  :disabled="item.disabled"
                  filterable
                  transfer
                  class="item-v"
                  @on-change="emitEvent(item, 'change')"
                >
                  <Option
                    v-for="(dd, ix) in optionItems[item.field]"
                    :key="ix"
                    :value="dd.value"
                  >
                    {{ $srv.getI18nBySrv(dd.label) }}
                  </Option>
                </Select>
                <oI18nSelector
                  class="item-v"
                  v-else-if="item.comp.name === 'oI18nSelector'"
                  :disabled="item.disabled"
                  v-model="item.value"
                  @on-enter="emitEvent(item, 'enter')"
                  @on-focus="emitEvent(item, 'focus')"
                  @on-blur="emitEvent(item, 'blur')"
                  @on-change="emitEvent(item, 'change')"
                  @mouseleave="emitEvent(item, 'mouseleave')"
                  @mouseenter="emitEvent(item, 'mouseenter')"
                ></oI18nSelector>
                <i-Switch
                  class="item-v"
                  v-else-if="item.comp.name === 'Switch'"
                  v-model="item.value"
                  :disabled="item.disabled"
                  :true-value="1"
                  :false-value="0 || ''"
                  @on-change="emitEvent(item, 'change')"
                ></i-Switch>
                <!-- <oIconbox
                  class="item-v"
                  v-else-if="item.comp.name === 'oIconbox'"
                  v-model="item.value"
                >
                </oIconbox> -->
                <DatePicker
                  v-else-if="item.comp.name === 'DatePicker'"
                  type="date"
                  v-model="item.value"
                  :disabled="item.disabled"
                  :format="'yyyy-MM-dd HH:mm:ss'"
                  @on-change="emitEvent(item, 'change')"
                ></DatePicker>
                <!-- <oRichText
                  v-else-if="item.comp.name === 'oRichText'"
                  v-model="item.value"
                ></oRichText> -->
              </p>
            </div>
          </div>
        </div>
        <div class="modal-footer">
          <Button v-if="rowStatus !== 'new'" type="error" @click="doDelete">
            {{ $t('others.delete') }}
          </Button>
          <Button type="info" @click="doEdit">
            {{ editStatus ? $t('others.cancelEdit') : $t('others.edit') }}
          </Button>
          <Button type="primary" :disabled="!isCanSave" @click="save">
            {{ $t('others.save') }}
          </Button>
        </div>
      </div>
    </template>
  </vxe-modal>
</template>
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator';
import { Tsrv, T_srv, ifs, ts, I_editor, vue, N_oBaseGrid } from './config';

@Component({ name: 'rowEditModal' })
export default class rowEditModal extends Vue {
  @Prop({ default: false, required: true })
  value!: boolean;

  @Prop({ default: 'none', required: true })
  rowStatus!: string;

  // 配置
  @Prop({
    type: Object,
    default: () => {}
  })
  config!: any;

  // 当前行数据
  @Prop({
    type: Object,
    default: () => {}
  })
  currentRowData!: any;

  @Prop({
    type: Array,
    default: () => {}
  })
  permission!: any;

  @Prop({
    type: Array,
    default: () => []
  })
  tableColumns!: any;

  @Prop({})
  tableEditor!: I_editor;

  private items: Array<any> = [];

  private cloneItms: Array<any> = [];

  optionItems = {};

  modalShow = false;

  private groupedItms: Object = {};

  private cloneGroupedItms: Object = {};

  changeData = {};

  sortDict = {};

  submitLoading = false;

  selectRow = null; // 标题

  private editStatus: boolean = false;

  private editPermission: boolean = true;

  private closeCheck: boolean = true;

  get isCanSave(): boolean {
    return !Tsrv.noValue(this.changeData) || this.rowStatus === 'new';
  }

  @Watch('value')
  watchValue(val: any) {
    this.modalShow = val;
    if (val) {
      this.closeCheck = true;
    }
  }

  @Watch('modalShow')
  watchModal1(val: any) {
    this.$emit('statusChangeCopy', val);
  }

  @Watch('groupedItms', { deep: true })
  watschModal2(val: any) {
    this.changeData = {};
    for (const item in val) {
      for (const i in val[item]) {
        if (val[item][i].value !== this.cloneGroupedItms[item][i].value) {
          this.changeData[val[item][i].field] = val[item][i].value;
        }
      }
    }
  }

  @Watch('currentRowData')
  watchCurrentRowData(val: any) {
    if (this.rowStatus === 'new') {
      this.editStatus = true;
    }
    this.optionItems = {};
    this.items = [];
    this.cloneItms = [];
    const cols = val.config.tableColumns;
    // json
    cols.forEach((e: any) => {
      const item = {
        field: e.field,
        formatter: e.formatter,
        // many2one: e.many2one,
        isShow: e.isShow,
        alias: e.comment,
        value: val.ev?.row[e.field] || '',
        isEdit: !Tsrv.utils.noValue(e.subQuery) || e.disabled,
        disabled: !Tsrv.utils.noValue(e.subQuery) || e.disabled,
        // !Tsrv.utils.noValue(e.subQuery) || e.disabled || !this.editStatus,
        required: e.required,
        actions: e.actions,
        groupTitle: this.fixFields(e.field)
      };
      const comp = { name: null, type: null };
      if (e.type.indexOf('varchar') !== -1) {
        if (e.formatter?.type === 'i18n') {
          comp.name = 'oI18nSelector';
        } else {
          comp.name = 'Input';
        }
      } else if (e.type.indexOf('mediumtext') !== -1) {
        comp.name = 'Input';
        comp.type = 'textarea';
      } else if (e.type.indexOf('json') !== -1) {
        comp.name = 'Input';
      } else if (e.type.indexOf('text') !== -1) {
        comp.name = 'Input';
      } else if (e.type.indexOf('bigint') !== -1) {
        comp.name = 'Input';
        comp.type = 'number';
      } else if (e.type.indexOf('smallint') !== -1) {
        comp.name = 'Input';
        comp.type = 'number';
      } else if (e.type.indexOf('decimal') !== -1) {
        comp.name = 'Input';
      } else if (e.type.indexOf('dateTime') !== -1) {
        comp.name = 'DatePicker';
        comp.type = 'date';
      } else if (e.type.indexOf('datetime') !== -1) {
        comp.name = 'DatePicker';
        comp.type = 'date';
      } else if (e.type.indexOf('date') !== -1) {
        comp.name = 'DatePicker';
        comp.type = 'date';
      } else if (e.type.indexOf('time') !== -1) {
        comp.name = 'Input';
      } else if (e.type.indexOf('bit') !== -1) {
        comp.name = 'Switch';
      } else if (e.type.indexOf('int') !== -1) {
        comp.name = 'Input';
        comp.type = 'number';
      }
      if (!Tsrv.utils.noValue(e.selectionID)) {
        // 下拉字段
        comp.name = 'valueSelect';
        const lang = this.$i18n.locale || 'en_US';
        const dbType = 'mysql';
        const id = e.selectionID;
        Tsrv.getSLCData(id, dbType, lang).then(([b, res, msg]) => {
          if (b) {
            this.$set(this.optionItems, e.field, res);
          } else {
            this.$msg(msg);
          }
        });
      }
      // 多对一
      // if (e.many2one?.toField !== '' && e.many2one?.toTable !== '') {
      if (
        !Tsrv.noValue(e.many2one?.toField) &&
        !Tsrv.noValue(e.many2one?.toTable)
      ) {
        // mto字段
        const many2one: any = {};
        comp.name = 'idSelect';
        // const m2oFind = this.tableColumns.find(ee => ee.title === e.field);
        // const m2oFind = this.tableColumns.find(
        //   ee => ee?.field.indexOf(`m2o|${e.field}`) > -1
        // );
        let m2oFind = null;
        this.tableColumns.forEach(ee => {
          if (
            !Tsrv.noValue(ee?.field) &&
            ee.field.indexOf(`m2o|${e.field}`) > -1
          ) {
            m2oFind = ee;
          }
        });
        if (m2oFind) {
          many2one['editRender'] = m2oFind?.editRender;
        }
        many2one.toField = e.many2one?.toField;
        many2one.toTable = e.many2one?.toTable;
        let fieldColumns = null;
        this.tableColumns.forEach(ee => {
          if (
            !Tsrv.noValue(ee?.field) &&
            ee.field.indexOf(`m2o|${e.field}`) > -1
          ) {
            fieldColumns = this.tableEditor
              .getGrid()
              .getColumnByField(ee.field);
          }
        });
        const params = {
          row: val.ev?.row,
          column: fieldColumns
        };
        // many2one['params'] = val.ev;
        many2one['params'] = params;
        item['many2one'] = many2one;
      }
      // if (e.formatter?.type === 'icon') {
      //   // 图标字段
      //   comp.name = 'oIconbox';
      // }
      // if (e.formatter?.type === 'richText') {
      //   // 富文本字段
      //   comp.name = 'oRichText';
      // }
      item['comp'] = comp;
      this.items.push(item);
    });
    this.handleGroup();
    this.updateEditStatus();
  }

  private handleGroup() {
    this.cloneItms = Tsrv.utils.clone(this.items, true);
    this.groupedItms = this.objectSort(
      Tsrv.utils.groupBy(Tsrv.utils.clone(this.items, true), 'groupTitle')
    );
    this.cloneGroupedItms = this.objectSort(
      Tsrv.utils.groupBy(Tsrv.utils.clone(this.items, true), 'groupTitle')
    );
    // if (Tsrv.utils.noValue(this.groupedItms['ungrouped'])) {
    //   delete this.groupedItms['ungrouped'];
    //   delete this.cloneGroupedItms['ungrouped'];
    // }
    if (Tsrv.utils.noValue(this.groupedItms['未分组'])) {
      delete this.groupedItms['未分组'];
      delete this.cloneGroupedItms['未分组'];
    }
  }

  // 字段整理
  public fixFields(field) {
    let groupTitle: string = '未分组';
    // let groupTitle: string = 'ungrouped';
    const fieldsConfig = this.config.groupByField;
    fieldsConfig.forEach(config => {
      if (config.fields.indexOf(field) !== -1) {
        groupTitle = config.groupTitle;
      }
    });
    return groupTitle;
  }

  private m2oChange(item, e) {
    item.value = e?.id;
  }

  created() {}

  mounted() {
    // setTimeout(() => {
    //   this.updateEditStatus();
    // }, 0);
    // this.$nextTick(() => {
    //   this.updateEditStatus();
    // });
  }

  beforeDestroy() {
    this.optionItems = {};
    this.items = [];
    this.cloneItms = [];
    this.groupedItms = {};
    this.cloneGroupedItms = {};
    this.editStatus = false;
  }

  private doEdit() {
    this.editStatus = !this.editStatus;
    this.updateEditStatus();
  }

  updateEditStatus() {
    this.items.forEach(el => {
      if (!el.isEdit) {
        el.disabled = !this.editStatus;
      }
    });
    this.handleGroup();
  }

  private doDelete() {
    this.closeCheck = false;
    if (this.currentRowData?.ev) {
      this.$emit('on-change', 'delete', this.currentRowData.ev?.row);
    }
    this.modalShow = false;
  }

  // 对象排序
  public objectSort(obj) {
    const newObj = {};
    const keys = Object.keys(obj);
    Tsrv.utils.remove(keys, item => item === '未分组');
    // Tsrv.utils.remove(keys, item => item === 'ungrouped');
    keys.push('未分组');
    // keys.push('ungrouped');
    keys.forEach(key => {
      newObj[key] = obj[key];
    });
    return newObj;
  }

  // 获取选项
  public getOptionItems(field) {
    return this.optionItems[field];
  }

  // 获取选项
  public getItems(field) {
    return this.items.filter(item => item.field === field);
  }

  // visibleMethod({ data }) {
  //   return data.flag1 === 'Y';
  // }

  // private getDS(d) {
  //   return (
  //     Tsrv.utils.find(
  //       this.optionItems[item.field],
  //       item => item.id === item.value
  //     )?.user_name || ''
  //   );
  // }
  hideModal() {
    return new Promise((resolve, reject) => {
      if (this.closeCheck) {
        if (Tsrv.utils.noValue(this.changeData)) {
          this.editStatus = false;
          resolve(true);
        } else {
          this.$Modal.confirm({
            title: Tsrv.getI18nByPath('others.isclosed') as string,
            content: Tsrv.getI18nByPath('others.isclosed') as string,
            onOk: () => {
              this.editStatus = false;
              resolve(true);
            },
            onCancel: () => {
              reject();
            }
          });
        }
      } else {
        resolve(true);
      }
    });
  }

  // handle处理字段事件
  private emitEvent(item: any, type: string) {
    // 完善：获取obasegrid组件的配置
    // 事件类型：focus、blur、change、enter、mouseleave、mouseenter、、

    const actions = item.actions;
    if (actions.findIndex((ite, index) => ite['eventType'] === type) === -1) {
      return;
    }

    if (item.field === 'id') {
      return;
    }
    this.$emit('on-field-event', this.currentRowData.ev, item, type);
  }

  private save() {
    this.closeCheck = false;
    this.submitLoading = true;
    setTimeout(() => {
      this.submitLoading = false;
      const L_cs = [];
      if (this.rowStatus === 'new') {
        // this.items.forEach((el: any) => {
        //   L_cs.push({ field: el.field, value: el.value });
        // });
        Object.keys(this.groupedItms).forEach(key => {
          this.groupedItms[key].forEach((el: any) => {
            L_cs.push({ field: el.field, value: el.value });
          });
        });
      } else {
        Tsrv.utils.objectEach(this.changeData, (item, key) => {
          L_cs.push({ field: key, value: item });
        });
        L_cs.push({ field: 'id', value: this.currentRowData.ev?.row.id });
      }
      const sw = [];
      this.currentRowData.config.tableColumns.forEach((el: any) => {
        // 如果是必填项
        if (el.required) {
          L_cs.forEach((e: any) => {
            if (e.field === el.field) {
              if (
                !e.value ||
                e.value === '' ||
                e.value === null ||
                e.value.length <= 0
              ) {
                sw.push(e.field);
              }
            }
          });
        }
        // 如果是 子查询 不纳入新增/修改字段中 （检查到L_cs中填入子查询字段，则移除）
        if (!Tsrv.utils.noValue(el.subQuery)) {
          if (!Tsrv.utils.noValue(el.subQuery)) {
            if (
              Tsrv.utils.findKey(L_cs, item => item.field === el.field) > -1
            ) {
              Tsrv.utils.remove(L_cs, item => item.field === el.field);
            }
          }
        }
      });
      if (sw.length > 0) {
        let str = '';
        sw.forEach((e: any) => {
          str += Tsrv.getI18nBySrv(e);
          str += ',';
        });
        str = str.substring(0, str.length - 1);
        this.$Message.info(str + this.$t('others.cannotBeEmpty'));
        return;
      }
      this.modalShow = false;
      const changeStatus = this.rowStatus === 'new' ? 'insert' : 'modify';
      if (L_cs.length > 1) {
        this.$emit('on-change', changeStatus, L_cs);
      }
      this.editStatus = false;
    }, 500);
  }
}
</script>
<style scoped lang="scss">
.modal {
  .modal-body {
    max-height: 70vh;
    display: flex;
    flex-wrap: nowrap;
    flex-direction: column;
    justify-content: start;
    .module {
      width: 100%;
      margin-bottom: 10px;
      display: flex;
      flex-direction: column;
      justify-content: start;
      .module-title {
        font-weight: 700;
        font-size: 13px;
        color: deepskyblue;
      }
      .module-content {
        display: flex;
        flex-wrap: wrap;
        padding-left: 35px;
        .item {
          display: inline-block;
          width: 45%;
          text-align: left;
          margin: 5px 0px;
          display: flex;
          justify-content: flex-start;
          margin-right: 30px;
          .item-k {
            white-space: nowrap;
            line-height: 4;
            .i-must-input-icon {
              margin-right: 3px;
              color: #f56c6c;
            }
            & {
              margin-right: 10px;
            }
          }
          .item-v {
            flex: 1;
            margin: 10px 0px;
          }
        }
      }
    }
  }

  .modal-footer {
    display: flex;
    justify-content: space-around;
  }
}
</style>
